package org.sixtynine.stock.controller;

import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Restrictions;
import org.sixtynine.stock.Constants.CommonData;
import org.sixtynine.stock.ReturnData;
import org.sixtynine.stock.dto.GridPramDTO;
import org.sixtynine.stock.dto.Page;
import org.sixtynine.stock.entity.AnnualShareData;
import org.sixtynine.stock.entity.BaseEntity;
import org.sixtynine.stock.entity.Company;
import org.sixtynine.stock.entity.QuarterlyShareData;
import org.sixtynine.stock.entity.User;
import org.sixtynine.stock.model.FileUploadForm;
import org.sixtynine.stock.model.LoadingSearchCriteria;
import org.sixtynine.stock.service.AnnualShareDataService;
import org.sixtynine.stock.service.CompanyService;
import org.sixtynine.stock.service.GenericService;
import org.sixtynine.stock.service.content.DataManagerService;
import org.sixtynine.stock.service.file.ExcelProcessorFactory;
import org.sixtynine.stock.service.file.FileDataService;
import org.sixtynine.stock.util.DateUtil;
import org.sixtynine.stock.util.SessionBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

/**
 * @author Thilan
 * 
 *         this class use to add , edit and delete Quarterly Share data
 * 
 */

@Controller
@SessionAttributes
public class AnnualShareController extends BackEndAuthController {

	/** TODO configure */
	private int RECORDS_PER_PAGE = 10;

	@Autowired
	private GenericService genericService;

	@Autowired
	private FileDataService fileDataService;

	@Autowired
	DataManagerService dataManagerService;

	@Autowired
	AnnualShareDataService annualShareDataService;

	@Autowired
	CompanyService companyService;

	@RequestMapping(value = "/admin/annualsharedata/search")
	public ModelAndView search(@ModelAttribute LoadingSearchCriteria criteria,
			HttpServletRequest request) {
		ModelAndView modelAndView = null;
		if (!isUserLogged(request)) {
			modelAndView = new ModelAndView("/login/login");
			modelAndView.addObject("registedUser", new User());
			return modelAndView;
		}

		modelAndView = new ModelAndView("/admin/annualsharedata/list");
		loadData(1, -1, criteria.getCompanyId(), criteria.getCompanyName(),
				criteria.getFromYear(), criteria.getToYear(), modelAndView,
				criteria);
		SessionBean sBean = SessionBean.getInstance(request);
		sBean.setAttr(SEARCH_CRITERIA, criteria);

		return modelAndView;
	}

	@RequestMapping(value = "/admin/annualsharedata/add")
	public ModelAndView addAnnualShareData(HttpServletRequest request) {

		ModelAndView modelAndView = null;

		if (!isUserLogged(request)) {
			modelAndView = new ModelAndView("/login/login");
			modelAndView.addObject("registedUser", new User());
			return modelAndView;
		}

		modelAndView = new ModelAndView("/admin/annualsharedata/add");
		modelAndView.addObject("annualShareData", new AnnualShareData());

		List<BaseEntity> companies = dataManagerService
				.getData(CommonData.COMPANY.toString());
		modelAndView.addObject("companyMap", companies);
		modelAndView.addObject("userLogged", true);

		return modelAndView;
	}

	@RequestMapping(value = "/admin/annualsharedata/add/file_process")
	public ModelAndView addingAnnualShareDataByFile(HttpServletRequest request,
			@ModelAttribute("uploadFile") FileUploadForm uploadFile) {

		ModelAndView modelAndView = null;
		modelAndView = new ModelAndView("/admin/annualsharedata/add");
		modelAndView.addObject("annualShareData", new AnnualShareData());

		boolean userLogged;
		SessionBean sessionBean = SessionBean.getInstance(request);

		MultipartFile multipartFile = uploadFile.getFile();

		ReturnData<String> fileSaveReturnData = fileDataService.saveFile(
				multipartFile,
				ExcelProcessorFactory.FILE_TYPE_ANNUAL_DATA_LIST, null);

		StringBuilder message = new StringBuilder();
		if (fileSaveReturnData._isSuccess()) {
			// if success, process it
			ReturnData<List<? extends BaseEntity>> returnData = fileDataService
					.process(multipartFile.getOriginalFilename(),
							ExcelProcessorFactory.FILE_TYPE_ANNUAL_DATA_LIST);
			if (returnData._isSuccess()) {
				message.append("file " + multipartFile.getOriginalFilename()
						+ " uploaded and inserted successfully");
				modelAndView = new ModelAndView("/admin/annualsharedata/list");
				loadData(1, -1, -1, null, 0, 0, modelAndView, null);
				// refresh data after insert
				dataManagerService.loadData(CommonData.COMPANY.toString(),
						Company.class);
			} else {

				message.append(returnData.getMsg());
			}
		} else {
			message.append(fileSaveReturnData.getMsg());
		}

		modelAndView.addObject("message", message);

		return modelAndView;
	}

	@RequestMapping(value = "/admin/annualsharedata/add/company_process")
	public ModelAndView addingAnnualShareDataByCompany(
			@ModelAttribute("uploadFile") FileUploadForm uploadFile) {

		ModelAndView modelAndView = null;
		modelAndView = new ModelAndView("/admin/annualsharedata/add");
		modelAndView.addObject("annualShareData", new AnnualShareData());

		MultipartFile multipartFile = uploadFile.getFile();
		ReturnData<String> fileSaveReturnData = fileDataService.saveFile(
				multipartFile,
				ExcelProcessorFactory.FILE_TYPE_COMPANY_ANNUAL_SHARE_DATA_LIST,
				null);

		StringBuilder message = new StringBuilder();
		if (fileSaveReturnData._isSuccess()) {
			// if success, process it
			ReturnData<List<? extends BaseEntity>> returnData = fileDataService
					.process(
							multipartFile.getOriginalFilename(),
							ExcelProcessorFactory.FILE_TYPE_COMPANY_ANNUAL_SHARE_DATA_LIST);
			if (returnData._isSuccess()) {
				message.append("file " + multipartFile.getOriginalFilename()
						+ " uploaded and inserted successfully");
				modelAndView = new ModelAndView("/admin/annualsharedata/list");

				loadData(1, -1, -1, null, 0, 0, modelAndView, null);

				// refresh data after insert
				dataManagerService.loadData(CommonData.COMPANY.toString(),
						Company.class);
			} else {
				modelAndView = new ModelAndView("/admin/annualsharedata/add");
				modelAndView
						.addObject("annualShareData", new AnnualShareData());

				List<BaseEntity> companies = dataManagerService
						.getData(CommonData.COMPANY.toString());
				modelAndView.addObject("companyMap", companies);
				modelAndView.addObject("userLogged", true);
				message.append(returnData.getMsg());
			}
		} else {
			modelAndView = new ModelAndView("/admin/annualsharedata/add");
			modelAndView.addObject("annualShareData", new AnnualShareData());

			List<BaseEntity> companies = dataManagerService
					.getData(CommonData.COMPANY.toString());
			modelAndView.addObject("companyMap", companies);
			modelAndView.addObject("userLogged", true);
			message.append(fileSaveReturnData.getMsg());
		}
		modelAndView.addObject("message", message);

		return modelAndView;
	}

	@RequestMapping(value = "/admin/annualsharedata/add/process")
	public ModelAndView addingAnnualShareData(
			@Valid @ModelAttribute AnnualShareData annualShareData,
			BindingResult result) {

		ModelAndView modelAndView = null;

		if (annualShareData.getYear() == 0) {
			modelAndView = new ModelAndView("/admin/annualsharedata/add");
			modelAndView.addObject("annualShareData", new AnnualShareData());

			List<BaseEntity> companies = dataManagerService
					.getData(CommonData.COMPANY.toString());
			modelAndView.addObject("companyMap", companies);
			modelAndView.addObject("userLogged", true);
			String message = "Please enter date correctly.";
			modelAndView.addObject("message", message);
			return modelAndView;
		}

		if (checkFutureYear(annualShareData.getYear())) {
			modelAndView = new ModelAndView("/admin/annualsharedata/add");
			modelAndView.addObject("annualShareData", new AnnualShareData());

			List<BaseEntity> companies = dataManagerService
					.getData(CommonData.COMPANY.toString());
			modelAndView.addObject("companyMap", companies);
			modelAndView.addObject("userLogged", true);
			String message = "Please enter date correctly.";
			modelAndView.addObject("message", message);
			return modelAndView;
		}

		Criterion criterion = (Restrictions.eq("year",
				annualShareData.getYear()));
		List<BaseEntity> dataList = genericService.findByCriteria(criterion,
				AnnualShareData.class);
		if (dataList.size() > 0) {
			modelAndView = new ModelAndView("/admin/annualsharedata/add");
			String message = "Data already exists for ."
					+ annualShareData.getYear();
			modelAndView.addObject("message", message);
		}

		if (!result.hasErrors()) {
			genericService.saveOrUpdate(annualShareData);
			modelAndView = new ModelAndView("/admin/annualsharedata/list");

			List<BaseEntity> annualShareDataList = genericService
					.findAll(AnnualShareData.class);
			modelAndView.addObject("annualShareDataList", annualShareDataList);
			String message = "Annual share data was successfully Added.";
			modelAndView.addObject("message", message);
			loadData(1, -1, annualShareData.getCompany().getId(),
					annualShareData.getCompany().getName(),
					annualShareData.getYear(), annualShareData.getYear(),
					modelAndView, null);
		} else {
			modelAndView = new ModelAndView("/admin/annualsharedata/add");
			modelAndView.addObject("annualShareData", new AnnualShareData());

			List<BaseEntity> companies = dataManagerService
					.getData(CommonData.COMPANY.toString());
			modelAndView.addObject("companyMap", companies);
			modelAndView.addObject("userLogged", true);
			String message = "Please enter data correctly.";
			modelAndView.addObject("message", message);
		}

		return modelAndView;

	}

	@RequestMapping(value = "/admin/annualsharedata/list")
	public ModelAndView listOfAnnualShareData(
			HttpServletRequest request,
			@RequestParam(value = "page", required = false) Integer page,
			@RequestParam(value = "totalRecords", required = false) Integer totalRecords) {

		ModelAndView modelAndView = null;

		if (!isUserLogged(request)) {
			modelAndView = new ModelAndView("/login/login");
			modelAndView.addObject("registedUser", new User());
			return modelAndView;
		}
		modelAndView = new ModelAndView("/admin/annualsharedata/list");
		loadData(page, totalRecords, -1, null, 0, 0, modelAndView, null);
		modelAndView.addObject("userLogged", true);

		return modelAndView;
	}

	/**
	 * load data
	 * 
	 * @param page
	 * @param totalRecords
	 * @param companyId
	 * @param fromDate
	 * @param toDate
	 * @param modelAndView
	 */
	private void loadData(Integer page, Integer totalRecords, int companyId,
			String companyName, int fromYear, int toYear,
			ModelAndView modelAndView, LoadingSearchCriteria criteria) {
		GridPramDTO gridPramDTO = new GridPramDTO();
		gridPramDTO.setRows(RECORDS_PER_PAGE);
		if (page != null) {
			gridPramDTO.setPage(page);
		} else {
			gridPramDTO.setPage(1);
		}
		if (totalRecords != null) {
			gridPramDTO._setTotalNumberOfRecords(totalRecords);
		}

		if (companyId == 0) {
			companyId = -1;
		}
		if (companyName == "") {
			companyName = null;
		}

		Page<AnnualShareData> annualShareDataPage = annualShareDataService
				.searchAnnualShareData(companyId, companyName, fromYear,
						toYear, "year", "company", gridPramDTO);
		modelAndView.addObject("annualShareDataPage", annualShareDataPage);

		List<BaseEntity> compaies = dataManagerService
				.getData(CommonData.COMPANY.toString());

		modelAndView.addObject("companyMap", compaies);
		if (criteria == null) {
			criteria = new LoadingSearchCriteria();

			criteria.setCompanyId(companyId);
			criteria.setCompanyName(companyName);
			criteria.setFromYear(fromYear);
			criteria.setToYear(toYear);
		}
		modelAndView.addObject("criteria", criteria);

	}

	@RequestMapping(value = "/admin/annualsharedata/edit/{id}", method = RequestMethod.GET)
	public ModelAndView editAnnualShareData(@PathVariable Integer id,
			HttpServletRequest request) {
		ModelAndView modelAndView = null;

		if (!isUserLogged(request)) {
			modelAndView = new ModelAndView("/login/login");
			modelAndView.addObject("registedUser", new User());
			return modelAndView;
		}
		modelAndView = new ModelAndView("/admin/annualsharedata/edit");
		BaseEntity annualShareData = genericService.findById(id,
				AnnualShareData.class);
		modelAndView.addObject("annualShareData", annualShareData);

		List<BaseEntity> companies = genericService.findAll(Company.class);
		modelAndView.addObject("companyMap", companies);

		return modelAndView;
	}

	@RequestMapping(value = "/admin/annualsharedata/edit/{id}", method = RequestMethod.POST)
	public ModelAndView edditingAnnualShareData(
			@Valid @ModelAttribute("annualShareData") AnnualShareData annualShareData,
			BindingResult result) {

		ModelAndView modelAndView = null;

		if (!result.hasErrors()) {

			genericService.saveOrUpdate(annualShareData);
			modelAndView = new ModelAndView("/admin/annualsharedata/list");

			List<BaseEntity> quarterlyShareDataList = genericService
					.findAll(QuarterlyShareData.class);
			modelAndView.addObject("annualShareDataList",
					quarterlyShareDataList);
			loadData(1, -1, annualShareData.getCompany().getId(),
					annualShareData.getCompany().getName(),
					annualShareData.getYear(), annualShareData.getYear(),
					modelAndView, null);
			String message = "Annual share data was successfully edited.";
			modelAndView.addObject("message", message);

			return modelAndView;
		} else {
			modelAndView = new ModelAndView("/admin/annualsharedata/edit");
			BaseEntity annualShareDataEdit = genericService.findById(
					annualShareData.getId(), AnnualShareData.class);
			modelAndView.addObject("annualShareData", annualShareDataEdit);

			List<BaseEntity> companies = genericService.findAll(Company.class);
			modelAndView.addObject("companyMap", companies);
			String message = "Pelase enter correct data.";
			modelAndView.addObject("message", message);

		}

		return modelAndView;

	}

	@RequestMapping(value = "/admin/annualsharedata/delete/{id}", method = RequestMethod.GET)
	public ModelAndView deleteAnnualShareData(@PathVariable Integer id) {

		genericService.delete(id, AnnualShareData.class);
		ModelAndView modelAndView = new ModelAndView(
				"/admin/annualsharedata/list");
		loadData(1, -1, -1, null, 0, 0, modelAndView, null);
		String message = "Annual share data was successfully deleted.";
		modelAndView.addObject("message", message);
		return modelAndView;
	}

	public boolean checkFutureYear(int year) {

		int currentYear = DateUtil.getYearFromDate(new Date());

		return currentYear < year;
	}

	@RequestMapping(value = "/admin/annualsharedata/deleteFiltered")
	public ModelAndView deleteFilteredAnnualShareData(HttpServletRequest request) {
		ModelAndView modelAndView = new ModelAndView(
				"admin/annualsharedata/list");

		if (!isUserLogged(request)) {
			modelAndView = new ModelAndView("/login/login");
			modelAndView.addObject("registedUser", new User());
			return modelAndView;
		}

		SessionBean sBean = SessionBean.getInstance(request);
		LoadingSearchCriteria criteria = (LoadingSearchCriteria) sBean
				.getAttr(SEARCH_CRITERIA);
		if (criteria == null) {
			criteria = new LoadingSearchCriteria();
		}

		if (criteria.getCompanyId() == 0) {
			criteria.setCompanyId(-1);
		}

		if (criteria.getCompanyName() != null
				&& !criteria.getCompanyName().isEmpty()) {

			Company company = companyService.findCompany(
					criteria.getCompanyName(), criteria.getCompanyId());

			if (company != null) {
				criteria.setCompanyId(company.getId());
			} else {
				criteria.setCompanyId(-1);
			}
		}
		// delete the selected criteria
		annualShareDataService.deleteAnnualShareData(criteria.getCompanyId(),
				criteria.getFromYear(), criteria.getToYear());

		// reload the page

		String message = "Successfully deleted filted data.";
		modelAndView.addObject("message", message);

		loadData(1, -1, -1, null, -1, -1, modelAndView, criteria);

		return modelAndView;
	}

}
